<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="../css/main.css" media="all" rel="stylesheet" type="text/css" />
<link href="../css/highlight.css" media="all" rel="stylesheet" type="text/css" />
<link href="../css/print.css" media="print" rel="stylesheet" type="text/css" />
<title>第19章 - symfonyの設定ファイルをマスターする</title>
</head>

<body>
<div class="navigation">

<table width="100%">
<tr>
<td width="40%" align="left"><a href="18-Performance.html">前の章</a></td>
<td width="20%" align="center"><a href="index.html">ホーム</a></td>
<td width="40%" align="right"><a href=""></a></td>
</tr>
</table>
<hr/>
</div>

<div>
<a name="chapter.19.mastering.symfonys.configuration.files" id="chapter.19.mastering.symfonys.configuration.files"></a><h1>第19章 - symfonyの設定ファイルをマスターする</h1>

<p>現在あなたはsymfonyをとてもよく理解しています。すでにコアの設計を理解し、新しい隠し機能を見つけるためにコードを徹底的に調べる準備ができています。しかし、独自要件に適用するためにsymfonyのクラスを拡張するまえに、設定ファイルをもっとよく見ることが必要です。すでに多くの機能はsymfonyに組み込まれ、設定を少し変更すれば有効になります。このことはクラスをオーバーライドしなくてもsymfonyコアのふるまいを調整できることを意味します。この章では設定ファイルとこれらの強力な機能を詳しく説明します。</p>

<div class="toc">
<dl>
<dt><a href="#symfony.settings">19.1. symfonyの設定</a></dt>
<dd><dl>
<dt><a href="#default.modules.and.actions">19.1.1. デフォルトのモジュールとアクション</a></dt>
<dt><a href="#optional.feature.activation">19.1.2. オプション機能の有効</a></dt>
<dt><a href="#feature.configuration">19.1.3. 機能のコンフィギュレーション</a></dt>
<dd><dl>
<dt><a href="#output.escaping.settings">19.1.3.1. 出力エスケーピングの設定</a></dt>
<dt><a href="#routing.settings">19.1.3.2. ルーティングの設定</a></dt>
<dt><a href="#form.validation.settings">19.1.3.3. フォームバリデーションの設定</a></dt>
<dt><a href="#cache.settings">19.1.3.4. キャッシュの設定</a></dt>
<dt><a href="#logging.settings">19.1.3.5. ロギングの設定</a></dt>
<dt><a href="#paths.to.assets">19.1.3.6. アセットへのパス</a></dt>
<dt><a href="#default.helpers">19.1.3.7. デフォルトのヘルパー</a></dt>
<dt><a href="#activated.modules">19.1.3.8. 有効なモジュール</a></dt>
<dt><a href="#character.set">19.1.3.9. 文字集合</a></dt>
<dt><a href="#miscellaneous.configuration">19.1.3.10. そのほかの設定</a></dt>
</dl></dd></dl></dd>
<dt><a href="#extending.the.autoloading.feature">19.2. オートロード機能を拡張する</a></dt>
<dt><a href="#custom.file.structure">19.3. カスタムファイル構造</a></dt>
<dd><dl>
<dt><a href="#the.basic.file.structure">19.3.1. 基本的なファイル構造</a></dt>
<dt><a href="#customizing.the.file.structure">19.3.2. ファイル構造をカスタマイズする</a></dt>
<dt><a href="#modifying.the.project.web.root">19.3.3. Web公開のrootディレクトリの修正</a></dt>
<dt><a href="#linking.to.symfony.libraries">19.3.4. symfonyのライブラリにリンクする</a></dt>
</dl></dd>
<dt><a href="#understanding.configuration.handlers">19.4. コンフィギュレーションハンドラーを理解する</a></dt>
<dd><dl>
<dt><a href="#default.configuration.handlers">19.4.1. デフォルトのコンフィギュレーションハンドラー</a></dt>
<dt><a href="#adding.your.own.handler">19.4.2. 独自ハンドラーを追加する</a></dt>
</dl></dd>
<dt><a href="#summary">19.5. まとめ</a></dt>
</dl>
</div>
<a name="symfony.settings" id="symfony.settings"></a><h2>symfonyの設定</h2>

<p><code>frontend/config/settings.yml</code>ファイルはおもに<code>frontend</code>アプリケーション用のsymfonyの設定を含みます。前の章でこのファイルから多くの設定の機能をすでに見てきましたが、再度これらを見ることにします。</p>

<p>5章で説明したように、このファイルは環境に依存します。すなわちそれぞれの設定が環境ごとに異なる値をとります。このファイルで定義されたそれぞれのパラメーターは<code>sfConfig</code>クラスを通してPHPクラスの内部からアクセスできることを覚えておいてください。パラメーター名は設定名にプレフィックスの<code>sf_</code>をつけたものです。たとえば、<code>cache</code>パラメーターの値を取得したい場合、必要なことは<code>sfConfig::get('sf_cache')</code>を呼び出すだけです。</p>

<a name="default.modules.and.actions" id="default.modules.and.actions"></a><h3>デフォルトのモジュールとアクション</h3>

<p>symfonyは特殊な状況に対してデフォルトページを用意します。ルーティングエラーの場合、symfonyは<code>default</code>モジュールのアクションを実行します。このモジュールは<code>$sf_symfony_lib_dir/controller/default/</code>ディレクトリに保存されています。<code>settings.yml</code>ファイルはエラーごとに実行されるアクションを定義します:</p>

<ul>
<li><code>error_404_module</code>と<code>error_404_action</code>: ユーザーによって入力されたURLがどのrouteにもマッチしないもしくは<code>sfError404Exception</code>が起動するときに呼び出されるアクションです。デフォルト値は<code>default/error404</code>です。</li>
<li><code>login_module</code>と<code>login_action</code>: <code>security.yml</code>ファイルのなかで<code>secure</code>と定義されたページに認証されていないユーザーがアクセスしようとするときに呼び出されるアクション(詳細は6章を参照)。デフォルト値は<code>default/login</code>です。</li>
<li><code>secure_module</code>と<code>secure_action</code>: ユーザーがアクションから求められるクレデンシャルを持たないときに呼び出されるアクションです。デフォルト値は<code>default/secure</code>です。</li>
<li><code>module_disabled_module</code>と<code>module_disabled_action</code>: ユーザーが<code>module.yml</code>ファイルのなかで無効と宣言されたモジュールをリクエストしたときに呼び出されるアクション。デフォルト値は<code>default/disabled</code>です。</li>
</ul>

<p>運用サーバーにデプロイするまえにこれらのアクションはアプリケーションをカスタマイズすべきです。<code>default</code>モジュールのテンプレートではページにsymfonyのロゴが含まれるからです。これらのページの1つのスクリーンショット、404エラーのページは図19-1をご覧ください。</p>

<p>図19-1 - デフォルトの404エラーページ</p>

<p><img src="images/F1901.jpg" alt="デフォルトの404エラーページ" title="デフォルトの404エラーページ" /></p>

<p>以下の2つの方法でデフォルトのページをオーバーライドできます:</p>

<ul>
<li>アプリケーションの<code>modules/</code>ディレクトリ内で独自のデフォルトモジュールを作成し、<code>settings.yml</code>ファイルで定義されたすべてのアクション(<code>index</code>、<code>error404</code>、<code>login</code>、<code>secure</code>、<code>disabled</code>)と関連するテンプレート(<code>indexSuccess.php</code>、<code>error404Success.php</code>、<code>loginSuccess.php</code>、 <code>secureSuccess.php</code>、<code>disabledSuccess.php</code>)をオーバーライドします。</li>
<li>アプリケーションのページを使うために<code>settings.yml</code>ファイルのデフォルトのモジュールとアクションの設定を変更できます。</li>
</ul>

<p>ほかの2つのページはsymfonyの見た目を有しており、運用サーバーにデプロイするまえにこれらのページはカスタマイズすることも必要です。これらのページは<code>default</code>モジュールには存在しません。これはsymfonyが適切に動作しないときに呼び出されるからです。代わりに、これらのデフォルトページは<code>$sf_symfony_lib_dir/exception/data/</code>ディレクトリで見つかります:</p>

<ul>
<li><code>error500.php</code>: 運用環境で内部のサーバーエラーが起きるときに呼び出されるページ。ほかの環境(<code>debug</code>が<code>true</code>に設定されている)においてエラーが起きるとき、symfonyはすべての実行スタックと明快なエラーメッセージを表示します(詳細は16章を参照)。</li>
<li><code>unavailable.php</code>: アプリケーションが(<code>disable</code>タスクで)無効にされている間にユーザーがページをリクエストしたときに呼び出されるページ。このページはキャッシュがクリアされている間も呼び出されます(すなわち、<code>php symfony cache:clear</code>タスクの呼び出しとこのタスクの終了時の間)。とても大きなキャッシュを持つシステム上では、キャッシュのクリア処理は数秒かかる可能性があります。symfonyは部分的にクリアしたキャッシュでリクエストを実行できないので、処理が終わるまえに受理されたリクエストはこのページにリダイレクトされます。</li>
</ul>

<p>これらのページをカスタマイズするには、プロジェクトもしくはアプリケーションの<code>web/errors/</code>ディレクトリのなかで<code>error500.php</code>ページと<code>unavailable.php</code>ページを作ります。symfonyは固有のページの代わりにこれらを使うようになります。</p>

<blockquote class="note"><p>
  必要なときにリクエストを<code>unavailable.php</code>ページにリダイレクトするには、アプリケーションの<code>settings.yml</code>のなかで<code>check_lock</code>設定を<code>on</code>にする必要があります。デフォルトではこの設定は無効です。この設定によってすべてのリクエストに対してわずかですがオーバーヘッドが追加されるからです。</p>
</blockquote>

<a name="optional.feature.activation" id="optional.feature.activation"></a><h3>オプション機能の有効</h3>

<p><code>settings.yml</code>ファイルのパラメーターのなかには有効もしくは無効にできるsymfonyのオプション機能をコントロールするものがあります。使わない機能を無効にすることでパフォーマンスが少し押し上げられるので、アプリケーションをデプロイするまえにテーブル19-1に示されている設定の一覧を見直してください。</p>

<p>テーブル 19-1 - <code>settings.yml</code>ファイルを通したオプション機能の一式</p>

<table>
<thead>
<tr>
  <th>パラメーター</th>
  <th>説明</th>
  <th>デフォルト値</th>
</tr>
</thead>
<tbody>
<tr>
  <td><code>use_database</code></td>
  <td>データベースマネージャを有効にする。データベースを使わない場合は<code>off</code>に切り替える。</td>
  <td><code>on</code></td>
</tr>
<tr>
  <td><code>i18n</code></td>
  <td>インターフェイスの翻訳機能を有効にする(13章を参照)。他言語アプリケーションのために<code>on</code>に設定する。</td>
  <td><code>off</code></td>
</tr>
<tr>
  <td><code>logging_enabled</code></td>
  <td>symfonyのイベントのロギングを有効にする。symfonyのロギング機能を完全にオフにしたい場合はoffに設定する。</td>
  <td><code>on</code></td>
</tr>
<tr>
  <td><code>escaping_strategy</code></td>
  <td>出力エスケーピング機能を有効にする(7章を参照)。テンプレートに渡すデータをエスケープしたい場合は<code>on</code>に設定する。</td>
  <td><code>off</code></td>
</tr>
<tr>
  <td><code>cache</code></td>
  <td>テンプレートキャッシュを有効にする(12章を参照)。モジュールの1つが<code>cache.yml</code>ファイルを含む場合に<code>on</code>に設定する。キャッシュフィルター(<code>sfCacheFilter</code>)が<code>on</code>になっている場合にのみ有効</td>
  <td>開発環境では<code>off</code>、運用環境では<code>on</code></td>
</tr>
<tr>
  <td><code>web_debug</code></td>
  <td>簡単なデバッグのためのWebデバッグツールバーを有効にする(16章を参照)。ツールバーをすべてのページに表示するには<code>on</code>に設定する。</td>
  <td>開発環境では<code>on</code>、運用環境では<code>off</code></td>
</tr>
<tr>
  <td><code>check_symfony_version</code></td>
  <td>すべてのリクエストに対してsymfonyのバージョンチェックを有効にする。symfonyをアップグレードした後に自動的にキャッシュをクリアするために<code>on</code>に設定する。アップグレードした後につねにキャッシュをクリアする場合は<code>off</code>のままにしておく。</td>
  <td><code>off</code></td>
</tr>
<tr>
  <td><code>check_lock</code></td>
  <td>アプリケーションのロックシステムを有効にする。<code>cache:clear</code>と<code>project:disable</code>タスクによって起動する(以前のセクションを参照)。<code>$sf_symfony_lib_dir/exception/data/unavailable.php</code>のページにリダイレクトするように無効なアプリケーションにリクエストを行うために<code>on</code>に設定する。</td>
  <td><code>off</code></td>
</tr>
<tr>
  <td><code>compressed</code></td>
  <td>PHPのレスポンス圧縮機能を有効にする。PHP圧縮ハンドラー経由で出力するHTMLを圧縮するには<code>on</code>にする。</td>
  <td><code>off</code></td>
</tr>
</tbody>
</table>

<a name="feature.configuration" id="feature.configuration"></a><h3>機能のコンフィギュレーション</h3>

<p>symfonyは組み込み機能、たとえば、バリデーション、キャッシュ、サードパーティのモジュールなどのふるまいを変更するにはいくつかの<code>settings.yml</code>ファイルのパラメーターを使います。</p>

<a name="output.escaping.settings" id="output.escaping.settings"></a><h4>出力エスケーピングの設定</h4>

<p>出力エスケーピングの設定は変数がテンプレートにアクセスする方法をコントロールします(7章を参照)。<code>settings.yml</code>ファイルはこの機能のために2つの設定を含みます:</p>

<ul>
<li><code>escaping_strategy</code>設定は<code>on</code>もしくは<code>off</code>の値を取ることができます。</li>
<li><code>escaping_method</code>設定は<code>ESC_RAW</code>、<code>ESC_SPECIALCHARS</code>、 <code>ESC_ENTITIES</code>、<code>ESC_JS</code>、もしくは<code>ESC_JS_NO_ENTITIES</code>の値に設定できます。</li>
</ul>

<a name="routing.settings" id="routing.settings"></a><h4>ルーティングの設定</h4>

<p>ルーティングの設定(9章を参照)は<code>factories.yml</code>ファイルのなかの<code>routing</code>キーの下で定義されます。リスト19-1はルーティングのデフォルトコンフィギュレーションを示しています。</p>

<p>リスト19-1 - ルーティングコンフィギュレーションの設定(<code>frontend/config/factories.yml</code>)</p>

<pre><code>routing:
  class: sfPatternRouting
  param:
    load_configuration: true
    suffix:             .
    default_module:     default
    default_action:     index
    variable_prefixes:  [':']
    segment_separators: ['/', '.']
    variable_regex:     '[\w\d_]+'
    debug:              %SF_DEBUG%
    logging:            %SF_LOGGING_ENABLED%
    cache:
      class: sfFileCache
      param:
        automatic_cleaning_factor: 0
        cache_dir:                 %SF_CONFIG_CACHE_DIR%/routing
        lifetime:                  31556926
        prefix:                    %SF_APP_DIR%
</code></pre>

<ul>
<li><code>suffix</code>パラメーターは生成されたURLのためにデフォルトのサフィックスを設定します。デフォルト値はピリオド(<code>.</code>)で、どの接尾辞にも一致しません。たとえば、すべての生成されたURLが静的なページに見えるように<code>.html</code>に設定します。</li>
<li>ルーティングルールが<code>module</code>パラメーターもしくは<code>action</code>パラメーターを定義しないとき、代わりに<code>factories.yml</code>ファイルからの値が使われます:

<ul>
<li><code>default_module</code>: デフォルトの<code>module</code>リクエストパラメーター。デフォルトは<code>default</code>モジュール。</li>
<li><code>default_action</code>: デフォルトの<code>action</code>リクエストパラメーター。デフォルトは<code>index</code>アクション。</li>
</ul></li>
<li>デフォルトでは、routeのパターンはコロンの(<code>:</code>)のプレフィックスによって名前つきのワイルドカードを識別します。PHPによりフレンドリな構文でルールを書きたいのであれば、ドル記号(<code>$</code>)を<code>variable_prefixes</code>配列に追加できます。この方法では、'/article/:year/:month/:day/:title'の代わりに'/article/$year/$month/$day/$title'のようなパターンを書けます。</li>
<li>パターンのルーティングは区切り文字の間の名前つきのワイルドカードを見分けます。デフォルトの区切り文字はスラッシュとドットですが、望むのであれば<code>segment_separators</code>パラメーターにより多くの区切り文字を追加できます。たとえば、ダッシュ(<code>-</code>)を追加したい場合、'/article/:year-:month-:day/:title'のようなパターンを書けます。</li>
<li>運用モードにおいて、外部URLと内部URIの間の変換を加速するために、パターンのルーティングは独自のキャッシュを使います。デフォルトでは、このキャッシュはファイルシステムを利用しますが、クラスと設定を<code>cache</code>パラメーターで宣言すれば任意のキャッシュクラスを使用できます。利用可能なキャッシュストレージクラスのリストに関しては15章を参照してください。運用環境でルーティングキャッシュを無効にするには、<code>debug</code>パラメーターを<code>on</code>に設定します。</li>
</ul>

<p><code>sfPatternRouting</code>クラス専用の設定があります。アプリケーションのルーティング、独自もしくはsymfonyのルーティングファクトリ(<code>sfNoRouting</code>と<code>sfPathInfoRouting</code>)の1つのどちらかに対して別のクラスを利用できます。これらの2つのどちらかを用いることで、すべての外部URLは'module/action?key1=param1'のようになります。カスタマイズする必要はありませんが、速いです。違いは最初のものはPHPの<code>GET</code>を使用し、2番目は<code>PATH_INFO</code>を使います。おもにバックエンドのインターフェイスにこれらを使います。</p>

<p>ルーティングに関連する追加パラメーターが1つありますが、これは <code>settings.yml</code>ファイルに保存されます:</p>

<ul>
<li><code>no_script_name</code>設定は生成されたURLのなかでフロントコントローラーを有効にします。フロントコントローラーをさまざまなディレクトリに保存してデフォルトのURL書き換えルールを変更しないかぎり、<code>no_script_name</code>設定はプロジェクト内の単独のアプリケーションに対してのみonです。通常この設定は運用環境のメインアプリケーションに対してonでその他に対してoffです。</li>
</ul>

<a name="form.validation.settings" id="form.validation.settings"></a><h4>フォームバリデーションの設定</h4>

<blockquote class="note"><p>
  このセクションで説明されている機能はsymfonyのバージョン1.1では廃止され<code>sfCompat10</code>プラグインを有効にしている場合のみに動作します。</p>
</blockquote>

<p>フォームバリデーションの設定は<code>Validation</code>ヘルパーによるエラーメッセージが表示される方法をコントロールします(10章を参照)。これらのエラーは<code>&lt;div&gt;</code>に含まれ、<code>id</code>属性を形成するためにこれらのエラーは<code>validation_error_class</code>設定と<code>validation_error_id_prefix</code>設定を<code>class</code>属性として使います。デフォルト値は<code>form_error</code>と<code>error_for_</code>なので、<code>foobar</code>という名前の入力に対して<code>form_error()</code>ヘルパーへの呼び出しによる属性出力は<code>class="form_error" id="error_for_foobar"</code>になります。</p>

<p>2つの設定はそれぞれのエラーメッセージ: <code>validation_error_prefix</code>と<code>validation_error_suffix</code>の前後に来る文字を決定します。一度にすべてのエラーメッセージをカスタマイズするためにこれらの設定を変更できます。</p>

<a name="cache.settings" id="cache.settings"></a><h4>キャッシュの設定</h4>

<p>キャッシュ設定の大部分は<code>cache.yml</code>ファイルで定義されますが、<code>settings.yml</code>ファイルのなかの2つは異なります: <code>cache</code>はテンプレートキャッシュのメカニズムを有効にし、<code>etag</code>はサーバーサイド上のETagハンドリングを有効にします(15章を参照)。<code>factories.yml</code>ファイルのなかで2つのすべてのキャッシュシステム(ビューキャッシュ、ルーティングキャッシュと、国際化キャッシュ)に対してどのストレージを使うのかを指定することもできます。リスト19-2はビューのキャッシュファクトリのデフォルトコンフィギュレーションを示しています。</p>

<p>リスト19-2 - ビューのキャッシュコンフィギュレーション(<code>frontend/config/factories.yml</code>)</p>

<pre><code>view_cache:
  class: sfFileCache
  param:
    automatic_cleaning_factor: 0
    cache_dir:                 %SF_TEMPLATE_CACHE_DIR%
    lifetime:                  86400
    prefix:                    %SF_APP_DIR%/template
</code></pre>

<p><code>class</code>の値は<code>sfFileCache</code>、<code>sfAPCCache</code>、<code>sfEAcceleratorCache</code>、<code>sfXCacheCache</code>、<code>sfMemcacheCache</code>、と <code>sfSQLiteCache</code>のどれかになります。<code>sfCache</code>を継承しキャッシュのキーの読みとりと削除をする、設定用の同じ一般的なメソッドを提供するのであれば、独自クラスも可能です。ファクトリのパラメーターは選んだクラスに依存しますが、定数が存在します:</p>

<ul>
<li><code>lifetime</code>はキャッシュが削除されるまでの秒数を定義します</li>
<li><code>prefix</code>はすべてのキャッシュキーに追加されるプレフィックスです(環境によって異なるキャッシュを利用するためにプレフィックスの環境を使う)。2つのアプリケーションのあいだでキャッシュを共有させたい場合は同じプレフィックスを使います。</li>
</ul>

<p>それぞれの特定のファクトリに関しては、キャッシュストレージの位置を定義しなければなりません。</p>

<ul>
<li><code>sfFileCache</code>に関しては、<code>cache_dir</code>パラメーターはキャッシュディレクトリへの絶対パスを探します</li>
<li><code>sfAPCCache</code>、<code>sfEAcceleratorCache</code>、と<code>sfXCacheCache</code>は位置パラメーターをとりません。これらがAPC、EAcceleratorもしくはXCacheキャッシュシステムとコミュニケーションするためにPHPのネイティブ関数を使うからです</li>
<li><code>sfMemcacheCache</code>に関しては、Memcachedサーバーのホスト名を<code>host</code>パラメーターに、もしくはホストの配列を<code>servers</code>パラメーターに入力します</li>
<li><code>sfSQLiteCache</code>に関しては、SQLiteデータベースファイルへの絶対パスは <code>database</code>パラメーターに入力されます。</li>
</ul>

<p>追加パラメーターに関しては、それぞれのキャッシュクラスのAPIドキュメントを確認してください。</p>

<p>ビューはキャッシュを使える唯一のコンポーネントではありません。<code>routing</code>ファクトリと<code>I18N</code>ファクトリの両方は、ビューキャッシュと同じように、キャッシュファクトリを設定できる<code>cache</code>パラメーターを提供します。たとえば、リスト19-1はデフォルトで加速戦術用にファイルキャッシュを使うルーティングを示していますが、望むものは何でも変更できます。</p>

<a name="logging.settings" id="logging.settings"></a><h4>ロギングの設定</h4>

<p>2つのロギングの設定(16章を参照)は<code>settings.yml</code>ファイルに保存されます:</p>

<ul>
<li><code>error_reporting</code>はPHPログに記録されるイベントを指定します。デフォルトでは、運用環境に対しては<code>E_PARSE | E_COMPILE_ERROR | E_ERROR | E_CORE_ERROR | E_USER_ERROR</code>に(ロギングされるイベントは<code>E_PARSE</code>、<code>E_COMPILE_ERROR</code>、<code>E_ERROR</code>、<code>E_CORE_ERROR</code>、と <code>E_USER_ERROR</code>)、開発環境では<code>E_ALL | E_STRICT</code>に設定されます。</li>
<li><code>web_debug</code>設定はWebデバッグツールバーを有効にします。開発とテスト環境のみでは<code>on</code>に設定します。</li>
</ul>

<a name="paths.to.assets" id="paths.to.assets"></a><h4>アセットへのパス</h4>

<p><code>settings.yml</code>ファイルはアセットへのパスも保存します。symfonyに搭載されたアセット以外の別のバージョンのアセットを使いたい場合、これらのパス設定を変更できます:</p>

<ul>
<li><code>rich_text_js_dir</code>に保存されるリッチなテキストエディタのJavaScriptファイル(デフォルトは<code>js/tiny_mce</code>)</li>
<li><code>prototype_web_dir</code>に保存されるPrototypeライブラリ(デフォルトは<code>/sf/prototype</code>)</li>
<li><code>admin_web_dir</code>に保存されadministrationジェネレーターが必要なファイル</li>
<li><code>web_debug_web_dir</code>に保存されWebデバッグツールバーが必要なファイル</li>
<li><code>calendar_web_dir</code>に保存されJavaScriptのカレンダーが必要なファイル</li>
</ul>

<a name="default.helpers" id="default.helpers"></a><h4>デフォルトのヘルパー</h4>

<p>デフォルトのヘルパーは、すべてのテンプレートに対してロードされ、<code>standard_helpers</code>設定で宣言されます(7章を参照)。デフォルトでは、これらは<code>Partial</code>、<code>Cache</code>、<code>Form</code>ヘルパーグループです。アプリケーションのすべてのテンプレート内部でヘルパーグループを利用する場合、<code>standard_helpers</code>設定にヘルパーグループの名前を追加すればそれぞれのテンプレート上で<code>use_helper()</code>ヘルパーを用いてヘルパーグループを宣言する煩わしい手続きを行わずにすみます。</p>

<a name="activated.modules" id="activated.modules"></a><h4>有効なモジュール</h4>

<p>プラグインもしくはsymfonyコアから有効にされるモジュールは<code>enabled_modules</code>パラメーターで宣言されます。プラグインがモジュールを搭載する場合、<code>enabled_modules</code>パラメーターで宣言されないかぎりユーザーはこのモジュールをリクエストできません。<code>default</code>モジュールはsymfonyのデフォルトページ(congratulations、page not foundページなど)を提供し、デフォルトで唯一有効なモジュールです。</p>

<a name="character.set" id="character.set"></a><h4>文字集合</h4>

<p>レスポンスの文字集合はアプリケーション全体の設定です。フレームワークの多くのコンポーネントで使われるからです(テンプレート、出力エスケーパ、ヘルパーなど)。定義される<code>charset</code>設定のデフォルト値は<code>utf-8</code>(推奨)です。</p>

<a name="miscellaneous.configuration" id="miscellaneous.configuration"></a><h4>そのほかの設定</h4>

<p><code>settings.yml</code>ファイルはコアのふるまいのためにsymfonyが内部で利用するいくつかのパラメーターを含みます。リスト19-3は設定ファイルに現れるパラメーターの一覧です。</p>

<p>リスト19-3 - そのほかの設定(<code>frontend/config/settings.yml</code>)</p>

<pre><code># symfonyのコアクラスのコメントをcore_compile.ymlファイルで定義されたものとして除去する
strip_comments:         on
# 例外の起動前のアクションの前のフォワードの最大回数
max_forwards:           5
# グローバル定数
path_info_array:        SERVER
path_info_key:          PATH_INFO
url_format:             PATH
</code></pre>

<blockquote class="sidebar"><p class="title">
  アプリケーションの設定を追加する</p>
  
  <p><code>settings.yml</code>ファイルはアプリケーションに対してsymfonyの設定を定義します。5章で説明したように新しいパラメーターを追加したい場合、最適の場所は<code>frontend/config/app.yml</code>ファイルです。このファイルは環境にも依存しており、このファイルが定義する設定の値は<code>sfConfig</code>クラスとプレフィックスの<code>app_</code>を通して利用できます。</p>

<pre><code>all:
  creditcards:
    fake:             off    # app_creditcards_fake
    visa:             on     # app_creditcards_visa
    americanexpress:  on     # app_creditcards_americanexpress
</code></pre>
  
  <p>プロジェクトの設定ディレクトリのなかで<code>app.yml</code>ファイルを書くこともでき、カスタムプロジェクト設定を定義できます。設定カスケードはこのファイルにも適用されるので、アプリケーションの<code>app.yml</code>ファイルで定義された設定はプロジェクトレベルで定義された設定をオーバーライドします。</p>
</blockquote>

<a name="extending.the.autoloading.feature" id="extending.the.autoloading.feature"></a><h2>オートロード機能を拡張する</h2>

<p>オートロード機能は2章で手短に説明しましたが、これによってコードが特定のディレクトリに設置していればクラスをrequireせずにすみます。このことは、symfonyに、必要なときだけ、適切な時点に必要なクラスだけをロードする作業を任せられることを意味します。</p>

<p><code>autoload.yml</code>ファイルはオートロードされたクラスが保存されるパスの一覧を示します。この設定ファイルが最初に処理されたとき、symfonyはこのファイルに参照されたすべてのディレクトリを解析します。<code>.php</code>の拡張子を持つファイルがこれらのディレクトリの1つのなかで見つかるたびに、このファイルのなかで見つかるファイルパスとクラス名がオートロードクラスの内部リストに追加されます。このリストはキャッシュ、<code>config/config_autoload.yml</code>ファイルに保存されます。それから、実行時に、クラスが使われたとき、このリストのなかでsymfonyはクラスのパスを探し<code>.php</code>ファイルを自動的にインクルードします。</p>

<p>オートロード機能はクラスかつ/またはインターフェイスを含むすべての<code>.php</code>ファイルに対して機能します。</p>

<p>デフォルトでは、つぎのプロジェクトディレクトリに保存されたクラスはオートロード機能からの恩恵を受けます:</p>

<ul>
<li><code>myproject/lib/</code></li>
<li><code>myproject/lib/model</code></li>
<li><code>myproject/apps/frontend/lib/</code></li>
<li><code>myproject/apps/frontend/modules/mymodule/lib</code></li>
</ul>

<p><code>autolaod.yml</code>ファイルはアプリケーションのデフォルトの設定ディレクトリ内には存在しません。symfonyの設定を修正したい場合、たとえばファイル構造のどこかに保存されたクラスをオートロードするには、空の<code>autoload.yml</code>ファイルを作り、<code>$sf_symfony_lib_dir/config/autoload.yml</code>ファイルもしくは独自ファイルの設定をオーバーライドします。</p>

<p><code>autoload.yml</code>ファイルは<code>autoload:</code>キーで始まり、symfonyがクラスを探す場所のリストを記載しなければなりません。それぞれの場所はラベルを必要とします: これによってsymfonyのエントリーをオーバーライドできます。それぞれの場所に対して、<code>name</code>(<code>config_autload.yml.php</code>でコメントとして表示される)と絶対パス(<code>path</code>)を記入してください。それから、検索が再帰的(<code>recursive</code>)であるように定義すると、symfonyはすべてのサブディレクトリで<code>.php</code>ファイルを探します。また望むサブディレクトリを除外(<code>exclude</code>)します。リスト19-2はデフォルトで使われる場所とファイルの構文を示しています。</p>

<p>リスト19-4 - オートロードのデフォルトコンフィギュレーション(<code>$sf_symfony_lib_dir/config/autoload.yml</code>)</p>

<pre><code>autoload:
  # プラグイン
  plugins_lib:
    name:           plugins lib
    path:           %SF_PLUGINS_DIR%/*/lib
    recursive:      on

  plugins_module_lib:
    name:           plugins module lib
    path:           %SF_PLUGINS_DIR%/*/modules/*/lib
    prefix:         2
    recursive:      on

  # プロジェクト
  project:
    name:           project
    path:           %SF_LIB_DIR%
    recursive:      on
    exclude:        [model, symfony]

  project_model:
    name:           project model
    path:           %SF_LIB_DIR%/model
    recursive:      on

  # アプリケーション
  application:
    name:           application
    path:           %SF_APP_LIB_DIR%
    recursive:      on

  modules:
    name:           module
    path:           %SF_APP_DIR%/modules/*/lib
    prefix:         1
    recursive:      on
</code></pre>

<p>ルールのパスにワイルドカードを含めることは可能で設定クラスのなかで定義されるファイルパスのパラメーターが使えます(つぎのセクションを参照)。設定ファイルのなかでこれらのパラメーターを使う場合、これらのパラメーターは大文字で始めと終わりを<code>%</code>で挟まなければなりません。</p>

<p>独自の<code>autoload.yml</code>ファイルを編集すれば 新しい位置がsymfonyのオートロード機能に追加されますが、このメカニズムを拡張してsymfonyのハンドラーに独自のオートロードハンドラーを追加したいことがあります。symfonyはクラスのオートロードを管理するために標準の<code>spl_autoload_register()</code>関数を使うので、アプリケーションの設定クラスに複数のコールバックを登録できます:</p>

<pre class="php"><span class="kw2">class</span> frontendConfiguration <span class="kw2">extends</span> sfApplicationConfiguration
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> initialize<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    parent<span class="sy0">::</span><span class="me2">initialize</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">// symfonyのオートロード機能を最初にロードする</span>
&nbsp;
    <span class="co1">// 独自のオートロードコールバックをここに挿入する</span>
    <span class="kw3">spl_autoload_register</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'myToolkit'</span><span class="sy0">,</span> <span class="st_h">'autoload'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>

<p>PHPのオートロードシステムは新しいクラスに遭遇するとき、最初にsymfonyのオートロードメソッドが試されます(そして<code>autoload.yml</code>ファイルのなかで定義された位置が使われます)。クラスの定義が見つからない場合、クラスが見つかるまで<code>spl_autoload_register()</code>で登録されたすべてのcallableが呼び出されます。たとえば、ほかのフレームワークコンポーネントへのブリッジを提供するために(17章参照)、望む数だけオートロードメカニズムを追加できます。</p>

<a name="custom.file.structure" id="custom.file.structure"></a><h2>カスタムファイル構造</h2>

<p>symfonyフレームワークは何か(コアクラスからテンプレート、プラグイン、設定、など)を探すためにパスを使うたびに、実際のパスの代わりにパス変数を使います。これらの変数を変更することで、symfonyプロジェクトのディレクトリ構造を完全に変更して、顧客のファイル構造の要件に適合させることができます。</p>

<blockquote class="caution"><p>
  symfonyプロジェクトのディレクトリ構造をカスタマイズするのは可能ですが、かならずしもよいアイディアではありません。symfonyのようなフレームワークの強みの一つは、規約を尊重されることでWeb開発者が慣習を尊重して開発されたプロジェクトを見て安心できることです。独自のディレクトリ構造を利用することを決定するまえにかならずこの問題を考えてください。</p>
</blockquote>

<a name="the.basic.file.structure" id="the.basic.file.structure"></a><h3>基本的なファイル構造</h3>

<p>パス変数は<code>sfProjectConfiguration</code>と<code>sfApplicationConfiguration</code>クラスのなかで定義され<code>sfConfig</code>オブジェクトに保存されます。リスト19-5はパス変数とこれらが参照するディレクトリの一覧を示しています。</p>

<p>リスト19-5 - <code>sfProjectConfiguration</code>と<code>sfApplicationConfiguration</code>のなかで定義された、デフォルトのファイル構造の変数</p>

<pre><code>sf_root_dir           # myproject/
sf_apps_dir           #   apps/
sf_app_dir            #     frontend/
sf_app_config_dir     #       config/
sf_app_i18n_dir       #       i18n/
sf_app_lib_dir        #       lib/
sf_app_module_dir     #       modules/
sf_app_template_dir   #       templates/
sf_cache_dir          #   cache/
sf_app_base_cache_dir #     frontend/
sf_app_cache_dir      #       prod/
sf_template_cache_dir #         templates/
sf_i18n_cache_dir     #         i18n/
sf_config_cache_dir   #         config/
sf_test_cache_dir     #         test/
sf_module_cache_dir   #         modules/
sf_config_dir         #   config/
sf_data_dir           #   data/
sf_doc_dir            #   doc/
sf_lib_dir            #   lib/
sf_log_dir            #   log/
sf_test_dir           #   test/
sf_plugins_dir        #   plugins/
sf_web_dir            #   web/
sf_upload_dir         #     uploads/
</code></pre>

<p>重要なディレクトリへのすべてのパスは<code>_dir</code>で終わるパラメーターによって決定されます。あとで必要なときにパスを変更できるように、本当の(相対もしくは絶対)ファイルパスの代わりにパス変数をつねに使用してください。たとえば、ファイルをアプリケーションの<code>uploads/</code>ディレクトリに移動させたいとき、パスに対して<code>sfConfig::get('sf_root_dir').'/web/uploads/'</code>の代わりに<code>sfConfig::get('sf_upload_dir')</code>を使います。</p>

<a name="customizing.the.file.structure" id="customizing.the.file.structure"></a><h3>ファイル構造をカスタマイズする</h3>

<p>アプリケーションを開発するさいに、顧客がすでにディレクトリ構造を定義しており、symfonyのロジックに適合させるために構造を変更する意志のない場合、おそらくデフォルトのプロジェクトファイル構造を修正する必要があります。<code>sf_XXX_dir</code>変数を<code>sfConfig</code>でオーバーライドすることで、デフォルトとはまったく異なるディレクトリ構造でsymfonyを動かすことができます。これを行う最良の場所はプロジェクトのディレクトリに対してはアプリケーションの<code>ProjectConfiguration</code>クラス、もしくはアプリケーションのディレクトリに対しては<code>XXXConfiguration</code>クラスです。</p>

<p>たとえば、すべてのアプリケーションにテンプレートのレイアウト用の共通ディレクトリを共有させたい場合、<code>sf_app_template_dir</code>設定をオーバーライドするためにつぎの行を<code>ProjectConfiguration</code>クラスの<code>configure()</code>メソッドに追加します:</p>

<pre class="php">sfConfig<span class="sy0">::</span><span class="me2">set</span><span class="br0">&#40;</span><span class="st_h">'sf_app_template_dir'</span><span class="sy0">,</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'sf_root_dir'</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="kw4">DIRECTORY_SEPARATOR</span><span class="sy0">.</span><span class="st_h">'templates'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<blockquote class="note"><p>
  <code>sfConfig::set()</code>を呼び出してプロジェクトのディレクトリ構造を変更できる場合でも、すべての関連パスの変更が考慮されるのでプロジェクトとアプリケーションの設定クラスによって定義された専用メソッドを使うほうが優れています。たとえば、<code>setCacheDir()</code>メソッドはつぎの定数: <code>sf_cache_dir</code>、<code>sf_app_base_cache_dir</code>、<code>sf_app_cache_dir</code>、<code>sf_template_cache_dir</code>、<code>sf_i18n_cache_dir</code>、<code>sf_config_cache_dir</code>、<code>sf_test_cache_dir</code>、と<code>sf_module_cache_dir</code>を変更します。</p>
</blockquote>

<a name="modifying.the.project.web.root" id="modifying.the.project.web.root"></a><h3>Web公開のrootディレクトリの修正</h3>

<p>設定クラスに組み込まれたすべてのパスはプロジェクトのrootディレクトリに依存します。このディレクトリパスはプロジェクトのなかの<code>ProjectConfiguration</code>ファイルによって決定されます。通常のrootディレクトリは<code>web/</code>ディレクトリの上位にありますが、異なる構造を利用できます。メインのディレクトリ構造が2つのディレクトリから構成される場合を考えてみます。リスト19-7で示されるように、1つのディレクトリは公開領域で、もう1つのディレクトリは非公開領域に存在します。プロジェクトを共用ホスティングサービス上でホストするときにこのコンフィギュレーションを選ぶことはよくあります。</p>

<p>リスト19-7 - 共用サーバーのためのカスタムディレクトリ構造の例</p>

<pre><code>symfony/    # 非公開領域
  apps/
  config/
  ...
www/        # 公開領域
  images/
  css/
  js/
  index.php
</code></pre>

<p>この場合、rootディレクトリは<code>symfony/</code>ディレクトリです。ですのでアプリケーションを動かすには<code>index.php</code>フロントコントローラーが<code>config/ProjectConfiguration.class.php</code>ファイルをインクルードすることがだけが必要です:</p>

<pre class="php"><span class="kw1">require_once</span><span class="br0">&#40;</span><span class="kw3">dirname</span><span class="br0">&#40;</span><span class="kw4">__FILE__</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/../symfony/config/ProjectConfiguration.class.php'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>加えて、つぎのように、公開領域を通常の<code>web/</code>から<code>www/</code>に変更するには<code>setWebDir()</code>メソッドを使います:</p>

<pre class="php"><span class="kw2">class</span> ProjectConfiguration <span class="kw2">extends</span> sfProjectConfiguration
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> setup<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="co1">// ...</span>
&nbsp;
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">setWebDir</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getRootDir</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/../www'</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>

<a name="linking.to.symfony.libraries" id="linking.to.symfony.libraries"></a><h3>symfonyのライブラリにリンクする</h3>

<p>リスト19-8で見られるように、symfonyへのパスは、<code>config/</code>ディレクトリ内に設置された、<code>ProjectConfiguration</code>クラスのなかで定義されます。</p>

<p>リスト19-8 - symfonyライブラリへのパス(<code>myproject/config/ProjectConfiguration.class.php</code>)</p>

<pre class="php"><span class="kw2">&lt;?php</span>
&nbsp;
<span class="kw1">require_once</span> <span class="st_h">'/path/to/symfony/lib/autoload/sfCoreAutoload.class.php'</span><span class="sy0">;</span>
sfCoreAutoload<span class="sy0">::</span><span class="me2">register</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="kw2">class</span> ProjectConfiguration <span class="kw2">extends</span> sfProjectConfiguration
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> setup<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>

<p>コマンドラインから<code>php symfony generate:project</code>タスクを呼び出すとき、パスは初期化され、プロジェクトをビルドするために使われるsymfonyの設置ディレクトリを参照します。これはコマンドラインとMVCアーキテクチャの両方から利用されます。</p>

<p>このことはsymfonyのファイルへのパスを変更することでsymfonyの別の設置ディレクトリに切り替え可能であることを意味します。</p>

<p>このパスは絶対パスでなければなりませんが、<code>dirname(__FILE__)</code>を利用することで、プロジェクト構造内部のファイルを参照してプロジェクトを設置するために選ばれたディレクトリの独立性を保つことができます。たとえば、つぎのコードのように、多くのプロジェクトがsymfonyの<code>lib/</code>ディレクトリをプロジェクトの<code>lib/vendor/symfony/</code>ディレクトリのシンボリックリンクとして設定します:</p>

<pre><code>myproject/
  lib/
    vendor/
      symfony/ =&gt; /path/to/symfony/
</code></pre>

<p>この場合、つぎのように<code>ProjectConfiguration</code>クラスはsymfonyのlibディレクトリを必要とするだけです:</p>

<pre class="php"><span class="kw2">&lt;?php</span>
&nbsp;
<span class="kw1">require_once</span> <span class="kw3">dirname</span><span class="br0">&#40;</span><span class="kw4">__FILE__</span><span class="br0">&#41;</span><span class="sy0">.</span><span class="st_h">'/../lib/vendor/symfony/lib/autoload/sfCoreAutoload.class.php'</span><span class="sy0">;</span>
sfCoreAutoload<span class="sy0">::</span><span class="me2">register</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="kw2">class</span> ProjectConfiguration <span class="kw2">extends</span> sfProjectConfiguration
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> setup<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>

<p>プロジェクトの<code>lib/vendor/</code>ディレクトリ内でsymfonyのファイルを<code>svn:externals</code>プロパティとして格納することを選んだ場合にも同じ原則があてはまります:</p>

<pre><code>myproject/
  lib/
    vendor/
      svn:externals symfony http://svn.symfony-project.com/branches/1.1
</code></pre>

<blockquote class="tip"><p>
  アプリケーションを稼働させているサーバーが異なる場合symfonyのライブラリへのパスが異なることがあります。これを有効にする1つの方法は(<code>rsync_exclude.txt</code>に追加することで)<code>ProjectConfiguration.class.php</code>ファイルを同期化の対象から除外することです。ほかの方法は開発と運用の両方の<code>ProjectConfiguration.class.php</code>ファイルで同じパスを保つことですが、シンボリックリンクを指し示すこれらのパスがサーバーによって変わる可能性があります。</p>
</blockquote>

<a name="understanding.configuration.handlers" id="understanding.configuration.handlers"></a><h2>コンフィギュレーションハンドラーを理解する</h2>

<p>それぞれの設定ファイルはハンドラーを持ちます。コンフィギュレーションハンドラー(configuration handler)の仕事は設定カスケードを管理することと、実行時に設定ファイルを最適化して実行可能なPHPコードに変換することです。</p>

<a name="default.configuration.handlers" id="default.configuration.handlers"></a><h3>デフォルトのコンフィギュレーションハンドラー</h3>

<p>デフォルトのハンドラー設定は<code>$sf_symfony_lib_dir/config/config/config_handlers.yml</code>ファイルに保存されます。このファイルはファイルパスにしたがってハンドラーを設定ファイルにリンクします。リスト19-9はこのファイルの内容を抜粋したものです。</p>

<p>リスト19-9 - <code>$sf_symfony_lib_dir/config/config/config_handlers.yml</code>ファイルの抜粋</p>

<pre><code>config/settings.yml:
  class:    sfDefineEnvironmentConfigHandler
  param:
    prefix: sf_

config/app.yml:
  class:    sfDefineEnvironmentConfigHandler
  param:
    prefix: app_

config/filters.yml:
  class:    sfFilterConfigHandler

modules/*/config/module.yml:
  class:    sfDefineEnvironmentConfigHandler
  param:
    prefix: mod_
    module: yes
</code></pre>

<p>それぞれの設定ファイルに対して(<code>config_handlers.yml</code>ファイルはワイルドカードを持つファイルパスでそれぞれのファイルを識別する)、ハンドラークラスは<code>class</code>キーの下で指定されます。</p>

<p><code>sfDefineEnvironmentConfigHandler</code>クラスによって処理される設定ファイルの設定は<code>sfConfig</code>クラスを通してコードのなかで直接利用できるようになり、<code>param</code>キーはプレフィックスの値を含みます。</p>

<p>設定ファイルを処理するために使われるハンドラーの追加もしくは修正ができます。たとえば、YAMLファイルの代わりに<code>INI</code>ファイルもしくは<code>XML</code>ファイルを使うためです。</p>

<blockquote class="note"><p>
  <code>config_handlers.yml</code>ファイル用のコンフィギュレーションハンドラーは<code>sfRootConfigHandler</code>クラスで、あきらかに変更できません。</p>
</blockquote>

<p>設定の解析方法を修正する必要がある場合、アプリケーションの<code>cofig/</code>フォルダー内に空の<code>config_handlers.yml</code>ファイルを作り、<code>class</code>キーの行を書いたクラスでオーバーライドします。</p>

<a name="adding.your.own.handler" id="adding.your.own.handler"></a><h3>独自ハンドラーを追加する</h3>

<p>設定ファイルを処理するハンドラーを利用することで2つの大きな利点がもたらされます:</p>

<ul>
<li>設定ファイルはPHPの実行コードに変換され、このコードはキャッシュに保存されます。このことは、運用環境において設定は1回だけ解析されるのでパフォーマンスが最適化されていることを意味します。</li>
<li>設定ファイルは異なるレベル(プロジェクトとアプリケーション)で定義することが可能で、最後のパラメーターの値はカスケードから由来します。プロジェクトレベルでパラメーターを定義し、アプリケーション単位でこれらをオーバーライドできます。</li>
</ul>

<p>独自のコンフィギュレーションハンドラーを書きたい場合、<code>$sf_symfony_lib_dir/config/</code>ディレクトリのなかでsymfonyによって使われる構造の例にしたがってください。</p>

<p>アプリケーションが<code>myMapAPI</code>クラスを含む場合を考えてみましょう。<code>myMapAPI</code>クラスは地図を配信するサードパーティのサービスのためのインターフェイスを提供します。リスト19-10で示されるように、このクラスはURLとユーザー名で初期化することが必要です。</p>

<p>リスト19-10 - <code>myMapAPI</code>クラスの初期化の例</p>

<pre class="php"><span class="re0">$mapApi</span> <span class="sy0">=</span> <span class="kw2">new</span> myMapAPI<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$mapApi</span><span class="sy0">-&gt;</span><span class="me1">setUrl</span><span class="br0">&#40;</span><span class="re0">$url</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$mapApi</span><span class="sy0">-&gt;</span><span class="me1">setUser</span><span class="br0">&#40;</span><span class="re0">$user</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p>アプリケーションの<code>config/</code>ディレクトリ内に設置された、<code>map.yml</code>という名前のカスタム設定ファイルでこれら2つのパラメーターを保存するとよいでしょう。この設定ファイルはつぎのような内容を含むことがあります:</p>

<pre><code>api:
  url:  map.api.example.com
  user: foobar
</code></pre>

<p>これらの設定をリスト19-8と同等なコードに変換するために、コンフィギュレーションハンドラーを作成しなければなりません。それぞれのコンフィギュレーションハンドラーは<code>sfConfigHandler</code>クラスを拡張し<code>execute()</code>メソッドを提供しなければなりません。<code>execute()</code>メソッドはパラメーターとして設定ファイルへのファイルパスの配列が必要で、キャッシュファイルに書き込まれるデータを返さなければなりません。YAMLファイル用のハンドラーは<code>sfYamlConfigHandler</code>クラスを拡張します。このクラスはYAMLパーサーのために追加のファシリティを提供します。<code>map.yml</code>ファイルに対する典型的なコンフィギュレーションハンドラーはリスト19-11で示されるように書けます。</p>

<p>リスト19-11 - カスタムコンフィギュレーションハンドラー(<code>frontend/lib/myMapConfigHandler.class.php</code>)</p>

<pre class="php"><span class="kw2">&lt;?php</span>
&nbsp;
<span class="kw2">class</span> myMapConfigHandler <span class="kw2">extends</span> sfYamlConfigHandler
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> execute<span class="br0">&#40;</span><span class="re0">$configFiles</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="co1">// yamlを解析する</span>
    <span class="re0">$config</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">parseYamls</span><span class="br0">&#40;</span><span class="re0">$configFiles</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$data</span>  <span class="sy0">=</span> <span class="st0">&quot;&lt;?php<span class="es1">\n</span>&quot;</span><span class="sy0">;</span>
    <span class="re0">$data</span> <span class="sy0">.=</span> <span class="st0">&quot;<span class="es1">\$</span>mapApi = new myMapAPI();<span class="es1">\n</span>&quot;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re0">$config</span><span class="br0">&#91;</span><span class="st_h">'api'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'url'</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <span class="re0">$data</span> <span class="sy0">.=</span> <span class="kw3">sprintf</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es1">\$</span>mapApi-&gt;setUrl('<span class="es6">%s</span>');<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> <span class="re0">$config</span><span class="br0">&#91;</span><span class="st_h">'api'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'url'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">isset</span><span class="br0">&#40;</span><span class="re0">$config</span><span class="br0">&#91;</span><span class="st_h">'api'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'user'</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <span class="re0">$data</span> <span class="sy0">.=</span> <span class="kw3">sprintf</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es1">\$</span>mapApi-&gt;setUser('<span class="es6">%s</span>');<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> <span class="re0">$config</span><span class="br0">&#91;</span><span class="st_h">'api'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'user'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw1">return</span> <span class="re0">$data</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre>

<p>symfonyが<code>execute()</code>メソッドに渡す<code>$configFiles</code>配列は<code>config/</code>フォルダーのなかで見つかるすべての<code>map.yml</code>ファイルへのパスを格納します。<code>parseYamls()</code>メソッドは設定カスケードを扱います。</p>

<p>この新しいハンドラーを<code>map.yml</code>ファイルと関連づけるには、つぎのような内容を持つ<code>config_handlers.yml</code>設定ファイルを作成しなければなりません:</p>

<pre><code>config/map.yml:
  class: myMapConfigHandler
</code></pre>

<blockquote class="note"><p>
  <code>class</code>はオートロードするか(上記の例)ファイルパスが<code>param</code>キーの下の<code>file</code>パラメーターで指定されたファイルのなかで定義しなければなりません。</p>
</blockquote>

<p>ほかの多くのsymfony設定ファイルに関しては、PHPコードにコンフィギュレーションハンドラーを直接追加することもできます:</p>

<pre><code>sfContext::getInstance()-&gt;getConfigCache()-&gt;registerConfigHandler('config/map.yml', 'myMapConfigHandler', array());
</code></pre>

<p>アプリケーション内部で<code>map.yml</code>ファイルに基づき<code>myMapConfigHandler</code>ハンドラーによって生成されたコードが必要な場合、つぎの行を呼び出してください:</p>

<pre class="php"><span class="kw1">include</span><span class="br0">&#40;</span>sfContext<span class="sy0">::</span><span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getConfigCache</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">checkConfig</span><span class="br0">&#40;</span><span class="st_h">'config/map.yml'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre>

<p><code>checkConfig()</code>メソッドを呼び出すとき、<code>map.yml.php</code>ファイルがキャッシュにまだ存在しないもしくは<code>map.yml</code>ファイルがキャッシュよりも新しい場合、symfonyは設定ディレクトリ内で既存の<code>map.yml</code>ファイルを探し<code>config_handlers.yml</code>ファイルで指定されたハンドラーを利用してこれらのファイルを処理します。</p>

<blockquote class="tip"><p>
  YAMLの設定ファイル内部で環境を扱いたい場合、ハンドラーは<code>sfYamlConfigHandler</code>クラスの代わりに<code>sfDefineEnvironmentConfigHandler</code>クラスを拡張できます。設定を読みとるには、<code>parseYaml()</code>メソッドの代わりに<code>getConfiguration()</code>メソッド: <code>$config = $this-&gt;getConfiguration($configFiles)</code>を呼び出します。</p>
</blockquote>

<p>-</p>

<blockquote class="sidebar"><p class="title">
  既存のコンフィギュレーションハンドラーを利用する</p>
  
  <p>ユーザーが<code>sfConfig</code>クラス経由でコードから値を読みとることができるようにする必要があるだけなら、<code>sfDefineEnvironmentConfigHandler</code>コンフィギュレーションハンドラークラスを利用できます。たとえば、<code>url</code>と<code>user</code>パラメーターをそれぞれ<code>sfConfig::get('map_url')</code>と<code>sfConfig::get('map_user')</code>として使えるようにするには、ハンドラーをつぎのように定義します:</p>

<pre><code>config/map.yml:
  class: sfDefineEnvironmentConfigHandler
  param:
    prefix: map_
</code></pre>
  
  <p>すでにほかのハンドラーによって使われているプレフィックスを選ばないように気をつけてください。 既存のプレフィックスは<code>sf_</code>、<code>app</code>、と<code>mod_</code>です。</p>
</blockquote>

<a name="summary" id="summary"></a><h2>まとめ</h2>

<p>設定ファイル(configuration file)はsymfonyフレームワークの動作方法を大いに変更します。symfonyはコア機能とファイルの読み込みでさえも設定に依存するので、標準の専用ホストよりも多くの環境に適用できます。このすばらしい設定の柔軟性はsymfonyの主要な強さの1つです。設定ファイルのなかで学ぶべきたくさんの規約を見た初心者を怖がらせることがあるにせよ、このことによってsymfony製のアプリケーションは膨大な数のプラットフォーム、環境に対して、互換性があります。ひとたびsymfonyの設定を習得したら、あなたのアプリケーションを動かすことを拒むサーバーは存在しないでしょう。</p>
</div>
<div class="navigation">
<hr/>
<table width="100%">
<tr>
<td width="40%" align="left"><a href="18-Performance.html">前の章</a></td>
<td width="20%" align="center"><a href="index.html">ホーム</a></td>
<td width="40%" align="right"><a href=""></a></td>
</tr>
</table>

</div>
</body>

</html>
